﻿using LetsDealData.Entities;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LetsDeal.Data
{
    public class LetsDealDbContext : LetsDealEntities
    {
        public int SaveChanges(int userId, int companyId)
        {
            // Get all Added/Deleted/Modified entities (not Unmodified or Detached)
            foreach (var entities in this.ChangeTracker.Entries()
                .Where(p => p.State == EntityState.Added
                    || p.State == EntityState.Deleted
                    || p.State == EntityState.Modified))
            {
                //var log = GetAuditRecordForChange(entities, userId);
                //if (log != null)
                //    this.Set<SysAuditLog>().Add(log);

                var log = GetAuditRecordForChange(entities, userId);
                //if (log != null)
                //{
                //    if (entities.ToString() == "LetsDealData.Entities.LetsDealEntities")
                //        this.entities.Set<eSuccess.Business.Entities.SysAuditLog>().Add((eSuccess.Business.Entities.SysAuditLog)log);
                //    else
                //    {
                //        this.entities.Set<eSuccess.Business.Entities.Organization.SysAuditLog>().Add((eSuccess.Business.Entities.Organization.SysAuditLog)log);
                //    }
                //}
            }
            return base.SaveChanges();
        }

        public object GetAuditRecordForChange(System.Data.Entity.Infrastructure.DbEntityEntry dbEntry, int userId)
        {
            DateTime changeTime = DateTime.Now;

            // Get the Table() attribute, if one exists
            TableAttribute tableAttr = dbEntry.Entity.GetType().GetCustomAttributes(typeof(TableAttribute), false).SingleOrDefault() as TableAttribute;

            // Get table name (if it has a Table attribute, use that, otherwise get the pluralized name)
            string tableName = tableAttr != null ? tableAttr.Name : dbEntry.Entity.GetType().Name;

            //XmlSerializer serializer = new XmlSerializer(current.GetType());
            //using (StringWriter writer = new StringWriter())
            //{
            //    serializer.Serialize(writer, current);
            //    currentvalue = writer.ToString();

            //}

            if (dbEntry.State == System.Data.EntityState.Added)
            {
                var current = dbEntry.CurrentValues.ToObject();
                string currentvalue = JsonConvert.SerializeObject(
                                  current,
                                  new JsonSerializerSettings()
                                  {
                                      NullValueHandling = NullValueHandling.Ignore,
                                      Formatting = Newtonsoft.Json.Formatting.Indented
                                  }).ToString();

                // For Inserts, just add the whole record
                // If the entity implements IDescribableEntity, use the description from Describe(), otherwise use ToString()
                return new
                {
                    UserId = userId,
                    EventTime = changeTime,
                    EventType = "A", // Added
                    ObjectName = tableName,
                    PropertiesChanged = "*ALL",
                    OriginalValue = "",
                    NewValue = currentvalue
                };
            }
            else
            {
                //TODO: serious problem here. load from DB will slow
                DbPropertyValues dBOriginalValues = dbEntry.GetDatabaseValues();
                var original = dBOriginalValues.ToObject();
                string originalValue = JsonConvert.SerializeObject(
                              original,
                              new JsonSerializerSettings()
                              {
                                  NullValueHandling = NullValueHandling.Ignore,
                                  Formatting = Newtonsoft.Json.Formatting.Indented
                              }).ToString();

                if (dbEntry.State == System.Data.EntityState.Deleted)
                {
                    // Same with deletes, do the whole record, and use either the description from Describe() or ToString()
                    return new
                    {
                        UserId = userId,
                        EventTime = changeTime,
                        EventType = "D", // Deleted
                        ObjectName = tableName,
                        PropertiesChanged = "*ALL",
                        OriginalValue = originalValue,
                        NewValue = ""
                    };
                }
                else if (dbEntry.State == System.Data.EntityState.Modified)
                {
                    string propertyChanged = "";

                    var current = dbEntry.CurrentValues.ToObject();
                    string currentvalue = JsonConvert.SerializeObject(
                                      current,
                                      new JsonSerializerSettings()
                                      {
                                          NullValueHandling = NullValueHandling.Ignore,
                                          Formatting = Newtonsoft.Json.Formatting.Indented
                                      }).ToString();

                    foreach (string propertyName in dbEntry.OriginalValues.PropertyNames)
                    {
                        // For updates, we only want to capture the columns that actually changed
                        if (!object.Equals(dBOriginalValues.GetValue<object>(propertyName), dbEntry.CurrentValues.GetValue<object>(propertyName)))
                        {
                            propertyChanged += propertyName + ";";
                        }
                    }
                    return new
                    {
                        UserId = userId,
                        EventTime = changeTime,
                        EventType = "M", //Modified
                        ObjectName = tableName,
                        PropertiesChanged = propertyChanged,
                        OriginalValue = originalValue,
                        NewValue = currentvalue
                    };
                }
            }
            // Otherwise, don't do anything, we don't care about Unchanged or Detached entities

            return null;
        }

        /*
        private SysAuditLog GetAuditRecordForChange(DbEntityEntry dbEntry, int userId)
        {

            DateTime changeTime = DateTime.Now;

            // Get the Table() attribute, if one exists
            TableAttribute tableAttr = dbEntry.Entity.GetType().GetCustomAttributes(typeof(TableAttribute), false).SingleOrDefault() as TableAttribute;

            // Get table name (if it has a Table attribute, use that, otherwise get the pluralized name)
            string tableName = tableAttr != null ? tableAttr.Name : dbEntry.Entity.GetType().Name;

            //XmlSerializer serializer = new XmlSerializer(current.GetType());
            //using (StringWriter writer = new StringWriter())
            //{
            //    serializer.Serialize(writer, current);
            //    currentvalue = writer.ToString();

            //}

            if (dbEntry.State == System.Data.EntityState.Added)
            {
                var current = dbEntry.CurrentValues.ToObject();
                string currentvalue = JsonConvert.SerializeObject(
                                  current,
                                  new JsonSerializerSettings()
                                  {
                                      NullValueHandling = NullValueHandling.Ignore,
                                      Formatting = Newtonsoft.Json.Formatting.Indented
                                  }).ToString();

                // For Inserts, just add the whole record
                // If the entity implements IDescribableEntity, use the description from Describe(), otherwise use ToString()
                return new SysAuditLog()
                        {
                            UserId = userId,
                            EventTime = changeTime,
                            EventType = "A", // Added
                            ObjectName = tableName,
                            PropertiesChanged = "*ALL",
                            OriginalValue = "",
                            NewValue = currentvalue
                        };
            }
            else
            {
                //TODO: serious problem here. load from DB will slow
                DbPropertyValues dBOriginalValues = dbEntry.GetDatabaseValues();
                var original = dBOriginalValues.ToObject();
                string originalValue  =JsonConvert.SerializeObject(
                              original,
                              new JsonSerializerSettings()
                              {
                                  NullValueHandling = NullValueHandling.Ignore,
                                  Formatting = Newtonsoft.Json.Formatting.Indented
                              }).ToString();

                if (dbEntry.State == System.Data.EntityState.Deleted)
                {
                    // Same with deletes, do the whole record, and use either the description from Describe() or ToString()
                    return new SysAuditLog()
                    {
                        UserId = userId,
                        EventTime = changeTime,
                        EventType = "D", // Deleted
                        ObjectName = tableName,
                        PropertiesChanged = "*ALL",
                        OriginalValue = originalValue,
                        NewValue = ""
                    };
                }
                else if (dbEntry.State == System.Data.EntityState.Modified)
                {
                    string propertyChanged = "";

                    var current = dbEntry.CurrentValues.ToObject();
                    string currentvalue = JsonConvert.SerializeObject(
                                      current,
                                      new JsonSerializerSettings()
                                      {
                                          NullValueHandling = NullValueHandling.Ignore,
                                          Formatting = Newtonsoft.Json.Formatting.Indented
                                      }).ToString();

                    foreach (string propertyName in dbEntry.OriginalValues.PropertyNames)
                    {
                        // For updates, we only want to capture the columns that actually changed
                        if (!object.Equals(dBOriginalValues.GetValue<object>(propertyName), dbEntry.CurrentValues.GetValue<object>(propertyName)))
                        {
                            propertyChanged += propertyName +";";
                        }
                    }
                    return new SysAuditLog()
                           {
                               UserId = userId,
                               EventTime = changeTime,
                               EventType = "M", //Modified
                               ObjectName = tableName,
                               PropertiesChanged = propertyChanged,
                               OriginalValue = originalValue,
                               NewValue = currentvalue
                           };
                }
            }
            // Otherwise, don't do anything, we don't care about Unchanged or Detached entities

            return null;
        }
         */
    }
}
